/*
** __SaM__'s HGE Addon
** Copyright (C) 2007 - 2008, Antonenko Artem
**
** HGE GUI Addon source file:
** shaGUIColorGraph
*/

#include "graphctrl.h"
#include <math.h>
#include <algorithm>

shaGUIColorGraph::shaGUIColorGraph(int id, float x, float y, float w, float h, float bLeft, float bRight, DWORD lineColor):
mark(0, 0, 0, COLMARK_W, COLMARK_H), fieldParts(0, 0, 0, w, h)
{
	this->id = id;
	bStatic = false;
	bVisible = true;
	bEnabled = true;

	this->x = x;
	this->y = y;
	this->w = w;
	this->h = h;

	rect.Set(x - COLMARK_W/2.0f, y, x + w + COLMARK_W/2.0f, y + h);

	leftBorder = bLeft;
	rightBorder = bRight;

	curMark = NULL;
	prevMark = NULL;
	nextMark = NULL;
	dx = fabs((rightBorder - leftBorder)/w);

	bkgColor = COLMARK_BKG;
	selColor = COLMARK_SEL;

	mark.SetHotSpot(COLMARK_W/2.0f, COLMARK_H/2.0f);

	marks.marks.push_back(colorMark(0xFFFFFFFF, 0));
	actions.push(MARK_ADD);

	colorField = new hgeTargetSprite(hge->Target_Create((int)w, (int)h, false), 0, 0, w, h);

	marks.color = lineColor;

	UpdateColorField();
}

shaGUIColorGraph::~shaGUIColorGraph()
{
	delete colorField;
}

void shaGUIColorGraph::Render()
{
	x = rect.x1 + COLMARK_W/2.0f;
	y = rect.y1;

	mark.SetColor(bkgColor);

	colorField->Render(x, y);

	iter = marks.marks.begin();
	nextIter = marks.marks.begin();
	nextIter++;
	endIter = marks.marks.end();
	while (iter != endIter)
	{
		x1 = (*iter).x;
		y1 = y + h/2.0f;
		GraphToScreen(&x1);

		if (nextIter == endIter)
		{
			x2 = x + w;
		}
		else
		{
			x2 = (*nextIter).x;
			GraphToScreen(&x2);
		}
		y2 = y + h/2.0f;

		hge->Gfx_RenderLine(x1, y1, x2, y2, marks.color);

		if (&(*iter) == curMark)
		{
			mark.SetColor(selColor);
			mark.Render(x1, y1);
			mark.SetColor(bkgColor);
		}
		else
		{
			mark.Render(x1, y1);
		}

		x1 -= COLMARK_W/2.0f;
		y1 -= COLMARK_H/2.0f;

		hge->Gfx_RenderLine(x1, y1, x1 + COLMARK_W, y1, marks.color);
		hge->Gfx_RenderLine(x1 + COLMARK_W, y1, x1 + COLMARK_W, y1 + COLMARK_H, marks.color);
		hge->Gfx_RenderLine(x1 + COLMARK_W, y1 + COLMARK_H, x1, y1 + COLMARK_H, marks.color);
		hge->Gfx_RenderLine(x1, y1 + COLMARK_H, x1, y1, marks.color);

		iter++;
		nextIter++;
	}
}

bool shaGUIColorGraph::MouseMove(float x, float y)
{
	if (hge->Input_GetKeyState(HGEK_LBUTTON) && curMark)
	{
		x += rect.x1;
		ScreenToGraph(&x);

		if (prevMark)
		{
			curMark->x = x;
		}

		if (nextMark && curMark->x > nextMark->x)
		{
			curMark->x = nextMark->x;
		}
		else if (prevMark && curMark->x < prevMark->x)
		{
			curMark->x = prevMark->x;
		}
		if (curMark->x > rightBorder)
		{
			curMark->x = rightBorder;
		}
		else if (curMark->x < leftBorder)
		{
			curMark->x = leftBorder;
		}
		UpdateColorField();
		actions.push(MARK_MOVE);
		return true;
	}
	return false;
}

bool shaGUIColorGraph::MouseLButton(bool bDown)
{
	hge->Input_GetMousePos(&x1, &y1);
	x1 -= rect.x1;
	y1 -= rect.y1;
	if (bDown)
	{
		curMark = NULL;

		iter = marks.marks.begin();
		endIter = marks.marks.end();
		while (iter != endIter)
		{
			x2 = (*iter).x;
			GraphToScreen(&x2);
			x2 -= rect.x1;

			if (x1 >= x2 - COLMARK_W/2.0f && x1 <= x2 + COLMARK_H && 
				y1 >= h/2.0f - 1.0f && y1 <= h/2.0f + 1.0f)
			{
				curMark = &(*iter);
				if (iter != marks.marks.begin())
				{
					iter--;
					prevMark = &(*iter);
					iter++;
				}
				else
				{
					prevMark = NULL;
				}
				iter++;
				if (iter != marks.marks.end())
				{
					nextMark = &(*iter);
				}
				else
				{
					nextMark = NULL;
				}
				actions.push(MARK_SEL);

				return true;
			}
			iter++;
		}

		iter = marks.marks.begin();
		nextIter = marks.marks.begin();
		endIter = marks.marks.end();
		nextIter++;
		while (iter != endIter)
		{
			x2 = x1 + rect.x1;
			y2 = y1;
			ScreenToGraph(&x2);

			if (nextIter != endIter && x2 >= (*iter).x && x2 <= (*nextIter).x &&
                y2 >= h/2.0f - 1.0f && y2 <= h/2.0f + 1.0f && marks.marks.size() < MAX_MARKS)
			{
				iter++;
				iter = marks.marks.insert(iter, colorMark((*iter).color, x2));
				UpdateColorField();
				actions.push(MARK_ADD);
				curMark = &(*iter);
				if (iter != marks.marks.begin())
				{
					iter--;
					prevMark = &(*iter);
					iter++;
				}
				else
				{
					prevMark = NULL;
				}
				iter++;
				if (iter != marks.marks.end())
				{
					nextMark = &(*iter);
					iter--;
				}
				else
				{
					nextMark = NULL;
				}

				return true;
			}
			else if (nextIter == endIter && x2 >= (*iter).x && y2 >= h/2.0f - 1.0f 
					&& y2 <= h/2.0f + 1.0f && marks.marks.size() < MAX_MARKS)
			{
				marks.marks.push_back(colorMark((*iter).color, x2));
				iter = marks.marks.end();
				iter--;
				UpdateColorField();
				actions.push(MARK_ADD);
				curMark = &(*iter);
				nextMark = NULL;
				if (iter != marks.marks.begin())
				{
					iter--;
					prevMark = &(*iter);
				}
				else
				{
					prevMark = NULL;
				}

				return true;
			}
			iter++;
			nextIter++;
		}
	}

	return false;
}

bool shaGUIColorGraph::KeyClick(int key, int chr)
{
	switch(key)
	{
	case HGEK_DELETE:
		if (curMark)
		{
			if (!prevMark)
			{
				break;
			}
			iter = find<ColIter, colorMark>(marks.marks.begin(), marks.marks.end(), *curMark);
			if (iter == --marks.marks.end())
			{
				iter--;
				curMark = &(*iter);
				if (iter != marks.marks.begin())
				{
					iter--;
					prevMark = &(*iter);
					iter++;
				}
				else
				{
					prevMark = NULL;
				}
				nextMark = NULL;
				iter++;
			}
			else if (iter == marks.marks.begin())
			{
				iter++;
				curMark = &(*iter);
				iter++;
				if (iter != marks.marks.end())
				{
					nextMark = &(*iter);
					iter--;
				}
				else
				{
					nextMark = NULL;
				}
				prevMark =  NULL;
				iter--;
			}
			else 
			{
                iter++;
				curMark = &(*iter);
				iter++;
				nextMark = &(*iter);
				iter--;
				iter--;
				iter--;
				prevMark = (&*iter);
				iter++;
			}
			marks.marks.erase(iter);
			UpdateColorField();
			actions.push(MARK_DEL);
			return true;
		}
		return false;
	default:
		return false;
	}
	return false;
}

void shaGUIColorGraph::GraphToScreen(float* x)
{
	*x /= dx;
	*x += this->x;
}

void shaGUIColorGraph::ScreenToGraph(float* x)
{
	*x -= this->x;
	*x *= dx;

}

void shaGUIColorGraph::UpdateColorField()
{
	bool clear = true;
	iter = marks.marks.begin();
	nextIter = marks.marks.begin();
	nextIter++;
	endIter = marks.marks.end();
	x1 = 0;
	x2 = 0;

	while (iter != endIter)
	{
		if (nextIter == endIter)
		{
			x1 = (rightBorder - (*iter).x)/dx;

			fieldParts.SetTextureRect(0, 0, x1, this->h);
			fieldParts.SetColor((*iter).color);

			hge->Gfx_BeginScene(colorField->GetTarget());
			if (marks.marks.size() == 1)
			{
				hge->Gfx_Clear(0);
			}
			fieldParts.Render(x2, 0.0f);
			hge->Gfx_EndScene();

			return;
		}
		x1 = ((*nextIter).x - (*iter).x)/dx;

		fieldParts.SetTextureRect(0, 0, x1, this->h);
		fieldParts.SetColor((*iter).color, 0);
		fieldParts.SetColor((*nextIter).color, 1);
		fieldParts.SetColor((*nextIter).color, 2);
		fieldParts.SetColor((*iter).color, 3);

		hge->Gfx_BeginScene(colorField->GetTarget());
		if (clear)
		{
			hge->Gfx_Clear(0);
			clear = false;
		}
		fieldParts.Render(x2, 0);
		hge->Gfx_EndScene();

		x2 += x1;
		iter++;
		nextIter++;
	}
}

void shaGUIColorGraph::InitGraph(list<colorMark> pnts)
{
	iter = pnts.begin();
	endIter = pnts.end();

	while (iter != endIter)
	{
		if ((*iter).x > rightBorder)
		{
			(*iter).x = rightBorder;
		}
		else if ((*iter).x < leftBorder)
		{

			(*iter).x = leftBorder;
		}
		iter++;
	}

	marks.marks.assign(pnts.begin(), pnts.end());
	UpdateColorField();
}